#include "mlx90614.h"

/********************************************************************************************************************************************************
函 数 名：void IIC_init()
功    能：IIC初始化
说    明：
入口参数：无
返 回 值：无
*********************************************************************************************************************************************************/
void IIC_Init(void)
{	
	csi_pin_set_mux(IIC_SCL, PIN_FUNC_GPIO); 
    csi_pin_set_mux(IIC_SDA, PIN_FUNC_GPIO); 

    csi_gpio_pin_init(&pin_SCL, IIC_SCL);
    csi_gpio_pin_dir(&pin_SCL, GPIO_DIRECTION_OUTPUT);
    csi_gpio_pin_init(&pin_SDA, IIC_SDA);
    csi_gpio_pin_dir(&pin_SDA, GPIO_DIRECTION_OUTPUT);	
	
	csi_gpio_pin_write(&pin_SCL, GPIO_PIN_HIGH);
	csi_gpio_pin_write(&pin_SDA, GPIO_PIN_HIGH);
	
	IIC_SCL1; 
	IIC_SDA1;
}

/********************************************************************************************************************************************************
函 数 名：void IIC_Start(void)
功    能：IIC起始信号
说    明：
入口参数：无
返 回 值：无
*********************************************************************************************************************************************************/
void IIC_Start(void)
{
	SDA_OUT();     //sda线输出
	IIC_SDA1;	
	delay_us(4);	
	IIC_SCL1;
	delay_us(4);
 	IIC_SDA0;//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL0;//钳住I2C总线，准备发送或接收数据 
	//delay_us(4);
}	  
/********************************************************************************************************************************************************
函 数 名：void IIC_Stop()
功    能：IIC停止信号
说    明：
入口参数：无
返 回 值：无
*********************************************************************************************************************************************************/

void IIC_Stop(void)
{
	SDA_OUT();//sda线输出
	IIC_SCL0;
	delay_us(4);
	IIC_SDA0;//STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL1; 
	delay_us(4);
	IIC_SDA1;//发送I2C总线结束信号
	delay_us(4);									   	
}
/********************************************************************************************************************************************************
函 数 名：void IIC_Wait_Ack(void)
功    能：IIC等待应答信号
说    明：
入口参数：无
返 回 值：ack
*********************************************************************************************************************************************************/
//等待应答信号到来
//返回值：1，接收应答失败
//        0，接收应答成功
uint8_t IIC_Wait_Ack(void)
{
	uint8_t ucErrTime=0;
	SDA_IN();      //SDA设置为输入  
	IIC_SDA1;delay_us(6);	   
	IIC_SCL1;delay_us(6);	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL0;//时钟输出0 	   
	return 0;  
} 
/********************************************************************************************************************************************************
函 数 名：void IIC_Ack(void)
功    能：IIC产生ACK应答信号
说    明：
入口参数：无
返 回 值：无
*********************************************************************************************************************************************************/

void IIC_Ack(void)
{
	IIC_SCL0;
	SDA_OUT();
	IIC_SDA0;
	delay_us(10);
	IIC_SCL1;
	delay_us(10);
	IIC_SCL0;
}
/********************************************************************************************************************************************************
函 数 名：void IIC_NAck(void)
功    能：IIC产生NACK应答信号
说    明：
入口参数：无
返 回 值：无
*********************************************************************************************************************************************************/
		    
void IIC_NAck(void)
{
	IIC_SCL0;
	SDA_OUT();
	IIC_SDA1;
	delay_us(10);
	IIC_SCL1;
	delay_us(10);
	IIC_SCL0;
}				
/********************************************************************************************************************************************************
函 数 名：void IIC_Send_Byte(uint8_t txd)
功    能：IIC发送一个字节
说    明：
入口参数：u8 txd
返 回 值：无
*********************************************************************************************************************************************************/
//IIC发送一个字节
//返回从机有无应答
//1，有应答
//0，无应答			  
void IIC_Send_Byte(uint8_t txd)
{                        
    uint8_t t;   
	SDA_OUT(); 	    
    IIC_SCL0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
		if((txd&0x80)>>7)
		{
			IIC_SDA1;
		}
		else
			IIC_SDA0;
		
        txd<<=1; 	  
		delay_us(10);   //对TEA5767这三个延时都是必须的
		IIC_SCL1;
		delay_us(10); 
		IIC_SCL0;	
		delay_us(10);
    }	 
} 	 
/********************************************************************************************************************************************************
函 数 名：u8 IIC_Read_Byte(unsigned char ack)
功    能：读一个字节
说    明：
入口参数：unsigned char ack 
返 回 值：u8 receive
*********************************************************************************************************************************************************/
//读1个字节，ack=1时，发送ACK，ack=0，发送nACK   
uint8_t IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
	{
        IIC_SCL0; 
        delay_us(10);
		IIC_SCL1;
        receive<<=1;
        if(READ_SDA)receive++;   
		delay_us(5); 
    }					 
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}

//IIC写一个字节数据
uint8_t IIC_Write_1Byte(uint8_t SlaveAddress, uint8_t REG_Address,uint8_t REG_data)
{
	IIC_Start();
	IIC_Send_Byte(SlaveAddress);
	if(IIC_Wait_Ack())
	{
		IIC_Stop();//释放总线
		return 1;//没应答则退出

	}
	IIC_Send_Byte(REG_Address);
	IIC_Wait_Ack();	
	IIC_Send_Byte(REG_data);
	IIC_Wait_Ack();	
	IIC_Stop();

	return 0;
}
//IIC读一个字节数据
uint8_t IIC_Read_1Byte(uint8_t SlaveAddress, uint8_t REG_Address,uint8_t *REG_data)
{
	IIC_Start();
	IIC_Send_Byte(SlaveAddress);//发写命令
	if(IIC_Wait_Ack())
	{
		 IIC_Stop();//释放总线
		 return 1;//没应答则退出
	}		
	IIC_Send_Byte(REG_Address);
	IIC_Wait_Ack();
	IIC_Start(); 
	IIC_Send_Byte(SlaveAddress|0x01);//发读命令
	IIC_Wait_Ack();
	*REG_data = IIC_Read_Byte(0);
	IIC_Stop();

	return 0;
}
//IIC写n字节数据
uint8_t IIC_Write_nByte(uint8_t SlaveAddress, uint8_t REG_Address,uint16_t len, uint8_t *buf)
{
	IIC_Start();
	IIC_Send_Byte(SlaveAddress);//发写命令
	if(IIC_Wait_Ack()) 
	{
		IIC_Stop();//释放总线
		return 1;//没应答则退出
	}
	IIC_Send_Byte(REG_Address);
	IIC_Wait_Ack();
	while(len--)
	{
		IIC_Send_Byte(*buf++);//发送buff的数据
		IIC_Wait_Ack();	
	}
	IIC_Stop();//释放总线

	return 0;
	
}

//IIC读n字节数据
uint8_t IIC_Read_nByte(uint8_t SlaveAddress, uint8_t REG_Address,uint16_t len,uint8_t *buf)
{
	IIC_Start();
	IIC_Send_Byte(SlaveAddress);//发写命令
	if(IIC_Wait_Ack()) 
	{
		IIC_Stop();//释放总线
		return 1;//没应答则退出
	}
	IIC_Send_Byte(REG_Address);
	IIC_Wait_Ack();

	IIC_Start();
	IIC_Send_Byte(SlaveAddress|0x01);//发读命令
	IIC_Wait_Ack();
	while(len)
	{
		if(len==1)
		{
			*buf = IIC_Read_Byte(0);
		}
		else
		{
			*buf = IIC_Read_Byte(1);
		}
		buf++;
		len--;
	}
	IIC_Stop();//释放总线

	return 0;
	
}

/********************************************************************************************************************************************************
函 数 名：float Get_Tem_DATA(U8 ReadAd)
功    能：IIC产生应答信号
说    明：
入口参数：无
返 回 值：无
*********************************************************************************************************************************************************/
float Get_Tem_DATA( uint8_t ReaAd)    //获取传感器所的温度值，℃，传入读取的RAM地址，输出摄氏度
{
	//从设备的地址 从0x00开始
   //使用读的过程 ：写读命令  ，每次从高位到低位 

	uint8_t Pecreg = 0;
	uint8_t DataL = 0 ,DataH = 0;
	uint16_t tem = 0;
	float Temp = 0;
	
	IIC_Start();
	
	IIC_Send_Byte(0x00); //  主机先发送写命令写入地址
	IIC_Wait_Ack();	
  	IIC_Send_Byte(ReaAd); //  RAM地址0x07可以获得温度的信息   

	IIC_Wait_Ack();
	//------------
	IIC_Start();
	IIC_Send_Byte(0x01);  //主机发送读命令  	，从上面传送的地址中读取数据
  	IIC_Wait_Ack();
	
  	DataL = IIC_Read_Byte(1);
  	DataH = IIC_Read_Byte(1);
  	Pecreg = IIC_Read_Byte(1);
	
  	IIC_Stop();
	
  	tem = (DataH<<8) | DataL;   //接收到传感器的16进制温度值
	
		//将16进制数值温度转换为℃  //不行，此处直接返回int型，会丢失小数数据，故还是返回浮点型
	Temp =  (((float)tem * 2) - 27315)/100;  //T= (DataH:DataL)*0.02-273.15  DataH:DataL=0x27AD,??? T=-70.01℃	  
	return Temp;
}